/*
 * To change this license header, choose License Headers in Project Properties.
 * To change this template file, choose Tools | Templates
 * and open the template in the editor.
 */
package pgentity.services;

import config.CFIBShop;
import config.CFIBShop.Price;
import config.CFSaleoff.Sale;
import config.PGConfig;
import pgentity.Penguin;
import pgentity.PenguinList;
import pgentity.Penguindex;
import pgentity.User;
import pgentity.quest.QuestLogger;
import share.PGError;
import db.PGKeys;
import logging.report.ActionRecord;
import logging.Logging;
import logging.report.UserAction;
import share.PGException;

/**
 *
 * @author Mrkupi
 */
public class ShopServices
{
    private ShopServices()
    {
        super();
    }

    private static final ShopServices inst = new ShopServices();

    public static ShopServices inst() {
        return inst;
    }
    
    public String[] buyPenguins(long now, final User user,
            QuestLogger userQLogger, final Penguindex penguindex,
            final PenguinList penguinList, String itemId, int nPeng) throws PGException
    {
        final String uid = user.getUid();
        final String coteID = penguinList.getCoteID();
        PGException.Assert(PGConfig.inst().getShopItems().containsKey(itemId),
                PGError.INVALID_ITEM, "Conf item was not found");
        
        config.CFIBShop.Item shopItem =
                PGConfig.inst().getShopItems().get(itemId);
        
        PGException.Assert("penguin".equals(shopItem.getKind()),
                PGError.ITEM_NOT_PENGUIN, "Item wasn't penguin");
        
        Price price = getItemPrice(itemId, now);
        assertItemRequirements(shopItem.getUnlockRequire(), price, nPeng, user);
        
        config.CFIBShop.PenguinShopItem penguinItem = (config.CFIBShop.PenguinShopItem) shopItem;
        
        String[] pengIDs = new String[nPeng];
        for( int i = 0; i < nPeng; ++i )
        {
            String pengId = PGKeys.randomKey();
            Penguin penguinEntity = Penguin.newPenguin(uid, coteID, pengId,
                    penguinItem.getEntity(), PGConfig.inst().temp().PenguinDefaultLevel,
                    now);

            pengIDs[i] = pengId;
        }
        penguindex.add(penguinItem.getEntity());
        penguinList.add(pengIDs);
        
        // Update user data
        int goldPrice = price.getGold() * nPeng;
        String paymentType = "";
        int priceVal = 0;
        if (goldPrice > 0)
        {
            UserServices.inst().decreaseGold(user, userQLogger, goldPrice,
                    now, UserAction.MUA_CHIM);
            paymentType = "gold";
            priceVal = goldPrice;
        }
        
        int coinPrice = price.getCoin() * nPeng;
        if (coinPrice > 0)
        {
            UserServices.inst().decreaseCoin(user, coinPrice,
                    now, UserAction.MUA_CHIM);
            paymentType = "coin";
            priceVal = coinPrice;
        }
        
        Logging.log(new ActionRecord(user, now, UserAction.MUA_CHIM,
                penguinItem.getEntity(), nPeng, paymentType, priceVal));
        
        return pengIDs;
    }
    
    public Boolean buyFish(final User user, QuestLogger userQLogger,
            String itemId, final long now) throws PGException
    {
        PGException.Assert(PGConfig.inst().getShopItems().containsKey(itemId),
                PGError.INVALID_ITEM, "Conf item was not found");
        
        config.CFIBShop.Item shopItem =
                PGConfig.inst().getShopItems().get(itemId);
        
        PGException.Assert("fish".equals(shopItem.getKind()), 
                PGError.ITEM_NOT_FISH, "Item wasn't fish");
        
        Price price = getItemPrice(itemId, now);
        assertItemRequirements(shopItem.getUnlockRequire(), price, 1, user);
        
        try
        {
            CFIBShop.FishShopItem fishItem = (CFIBShop.FishShopItem) shopItem;
            UserServices.inst().changeFish(user, userQLogger, fishItem.getnFish(), now);
            
            // Update user data
            String payType = "";
            int priceVal = 0;
            int goldPrice = price.getGold();
            if (goldPrice > 0)
            {
                UserServices.inst().decreaseGold(user, userQLogger, goldPrice,
                        now, UserAction.MUA_CA);
                payType = "gold";
                priceVal = goldPrice;
            }

            int coinPrice = price.getCoin();
            if (coinPrice > 0)
            {
                UserServices.inst().decreaseCoin(user, coinPrice,
                        now, UserAction.MUA_CA);
                payType = "coin";
                priceVal = coinPrice;
            }
            
            Logging.log(new ActionRecord(user, now, UserAction.MUA_CA,
                    itemId, "fish", fishItem.getnFish(), payType, priceVal));
        } catch(ClassCastException e)
        {
            throw new PGException(PGError.ITEM_NOT_FISH, "Fish config match item was not found");
        }
        
        return true;
    }
    
    public Boolean buyGold(final User user, String itemId,
            final QuestLogger uLogger, final long now)
    {
        PGException.Assert(PGConfig.inst().getShopItems().containsKey(itemId),
                PGError.INVALID_ITEM, "Conf item was not found");
        
        config.CFIBShop.Item shopItem =
                PGConfig.inst().getShopItems().get(itemId);
        
        PGException.Assert("gold".equals(shopItem.getKind()), 
                PGError.ITEM_NOT_GOLD, "Item wasn't gold");
        
        Price price = getItemPrice(itemId, now);
        assertItemRequirements(shopItem.getUnlockRequire(), price, 1, user);
        
        try
        {
            CFIBShop.GoldShopItem goldItem = (CFIBShop.GoldShopItem) shopItem;
            UserServices.inst().increaseGold(user, uLogger, goldItem.getnGold(), now,
                    UserAction.MUA_VANG);
            
            // update
            int coinPrice = price.getCoin();
            UserServices.inst().decreaseCoin(user, coinPrice, now,
                    UserAction.MUA_VANG);
            
            Logging.log(new ActionRecord(user, now, UserAction.MUA_VANG,
                    itemId, "gold", goldItem.getnGold(), "coin", coinPrice));
        } catch(ClassCastException e)
        {
            throw new PGException(PGError.ITEM_NOT_GOLD, "Gold config match item was not found");
        }
        
        return true;
    }
    
    private void assertItemRequirements(CFIBShop.Item.UnlockRequirement req, Price price,
            int nItems, User user) throws PGException
    {
        PGException.Assert(req.getLevel() <= user.getLevel(),
                PGError.NOT_ENOUGH_LEVEL, "Not enough level (" + user.getLevel() +
                        "/" + req.getLevel() + ")");
        PGException.Assert(price.getCoin() * nItems <= user.getCoin(),
                PGError.NOT_ENOUGH_COIN, "Not enough coin (" + user.getCoin() +
                        "/" + price.getCoin() * nItems + ")");
        PGException.Assert(price.getGold()* nItems <= user.getGold(),
                PGError.NOT_ENOUGH_GOLD, "Not enough gold (" + user.getGold() +
                        "/" + price.getGold() * nItems + ")");
    }
    
    private CFIBShop.Price getItemPrice(String item, long now)
    {
        Sale sale = PGConfig.inst().getSaleoff().getSale(now);
        if (sale != null && sale.getIbshop().containsKey(item))
        {
            return sale.getIbshop().get(item);
        }
        
        return PGConfig.inst().getShopItems().getItemPrice(item);
    }
}